//! # Unichar - Unicode字符和图标管理库
//! 
//! 这个库提供了一个灵活的Unicode字符和图标管理系统，支持通过配置来切换不同的显示样式。
//! 
//! ## 主要功能
//! 
//! - 内置丰富的Unicode字符和图标映射表
//! - 支持多种显示样式配置
//! - 通过简单的API访问不同样式的字符
//! - 支持自定义配置和扩展
//! - 支持字符别名和样式回退
//! - 支持从文件加载/保存配置
//! 
//! ## 使用示例
//! 
//! ```rust
//! use unichar::{Unichar, Config, Style};
//! 
//! // 创建实例
//! let mut unichar = Unichar::new();
//! 
//! // 获取成功字符（使用默认样式）
//! println!("Success: {}", unichar.get("success").unwrap_or(""));
//! 
//! // 切换到图标样式
//! unichar.set_config(Config::new().with_style(Style::Icon));
//! println!("Success icon: {}", unichar.get("success").unwrap_or(""));
//! 
//! // 使用预设配置
//! let mut rich = Unichar::with_config(Config::Presets::rich());
//! println!("Rich success: {}", rich.get("success").unwrap_or(""));
//! ```

pub mod config;
pub mod characters;
pub mod error;

pub use config::*;
pub use characters::*;
pub use error::*;

use std::collections::HashMap;

/// Unicode字符和图标管理器
#[derive(Debug, Clone)]
pub struct Unichar {
    /// 当前配置
    config: Config,
    /// 字符映射表
    characters: HashMap<String, CharacterSet>,
}

impl Unichar {
    /// 创建新的Unichar实例，使用默认配置
    pub fn new() -> Self {
        Self::with_config(Config::default())
    }

    /// 创建新的Unichar实例，使用指定配置
    pub fn with_config(config: Config) -> Self {
        Self {
            config,
            characters: get_default_characters(),
        }
    }

    /// 获取指定名称的字符，使用当前配置的样式
    /// 
    /// 如果指定的样式不存在，会尝试使用回退样式
    pub fn get(&self, name: &str) -> Option<&str> {
        let resolved_name = self.config.resolve_character_name(name);
        self.get_with_style(&resolved_name, &self.config.style)
    }

    /// 获取指定名称和样式的字符
    pub fn get_with_style(&self, name: &str, style: &Style) -> Option<&str> {
        let resolved_name = self.config.resolve_character_name(name);
        self.characters.get(&resolved_name).and_then(|char_set| char_set.get(style))
    }

    /// 获取指定名称的字符，带样式回退
    /// 
    /// 如果指定的样式不存在，会按照优先级尝试其他样式
    pub fn get_with_fallback(&self, name: &str) -> Option<&str> {
        let resolved_name = self.config.resolve_character_name(name);
        let char_set = self.characters.get(&resolved_name)?;
        
        // 尝试所有回退样式
        for style in self.config.get_style_fallback() {
            if let Some(char) = char_set.get(&style) {
                return Some(char);
            }
        }
        
        None
    }

    /// 更新配置
    pub fn set_config(&mut self, config: Config) {
        self.config = config;
    }

    /// 获取当前配置的引用
    pub fn config(&self) -> &Config {
        &self.config
    }

    /// 获取当前配置的可变引用
    pub fn config_mut(&mut self) -> &mut Config {
        &mut self.config
    }

    /// 添加自定义字符集
    pub fn add_character_set(&mut self, name: String, character_set: CharacterSet) {
        self.characters.insert(name, character_set);
    }

    /// 移除字符集
    pub fn remove_character_set(&mut self, name: &str) -> Option<CharacterSet> {
        self.characters.remove(name)
    }

    /// 获取所有可用的字符名称
    pub fn available_characters(&self) -> Vec<&String> {
        self.characters.keys().collect()
    }

    /// 检查是否存在指定名称的字符
    pub fn has_character(&self, name: &str) -> bool {
        let resolved_name = self.config.resolve_character_name(name);
        self.characters.contains_key(&resolved_name)
    }

    /// 获取指定字符的所有可用样式
    pub fn get_available_styles(&self, name: &str) -> Vec<Style> {
        let resolved_name = self.config.resolve_character_name(name);
        self.characters
            .get(&resolved_name)
            .map(|char_set| char_set.available_styles())
            .unwrap_or_default()
    }

    /// 从JSON字符串加载配置
    pub fn load_config_from_json(&mut self, json: &str) -> Result<()> {
        let config = Config::from_json(json)?;
        self.config = config;
        Ok(())
    }

    /// 将当前配置保存为JSON字符串
    pub fn save_config_to_json(&self) -> Result<String> {
        self.config.to_json()
    }

    /// 从文件加载配置
    pub fn load_config_from_file<P: AsRef<std::path::Path>>(&mut self, path: P) -> Result<()> {
        let config = Config::from_file(path)?;
        self.config = config;
        Ok(())
    }

    /// 保存当前配置到文件
    pub fn save_config_to_file<P: AsRef<std::path::Path>>(&self, path: P) -> Result<()> {
        self.config.save_to_file(path)
    }

    /// 批量获取字符
    /// 
    /// 返回一个HashMap，包含所有请求的字符名称及其对应的字符
    pub fn get_multiple(&self, names: &[&str]) -> HashMap<String, Option<&str>> {
        let mut result = HashMap::new();
        for &name in names {
            let char = self.get(name);
            result.insert(name.to_string(), char);
        }
        result
    }

    /// 格式化字符串，将{name}占位符替换为对应的字符
    /// 
    /// 例如：format("Status: {success}") -> "Status: ✓"
    pub fn format(&self, template: &str) -> String {
        let mut result = String::new();
        let mut chars = template.chars().peekable();
        
        while let Some(ch) = chars.next() {
            if ch == '{' {
                let mut name = String::new();
                while let Some(&next_ch) = chars.peek() {
                    if next_ch == '}' {
                        chars.next(); // 消费 '}'
                        if let Some(char_str) = self.get(&name) {
                            result.push_str(char_str);
                        } else {
                            result.push('{');
                            result.push_str(&name);
                            result.push('}');
                        }
                        break;
                    } else {
                        name.push(chars.next().unwrap());
                    }
                }
            } else {
                result.push(ch);
            }
        }
        
        result
    }

    /// 获取字符统计信息
    pub fn get_stats(&self) -> CharacterStats {
        let total_characters = self.characters.len();
        let mut style_counts = HashMap::new();
        
        for char_set in self.characters.values() {
            for style in char_set.available_styles() {
                *style_counts.entry(style).or_insert(0) += 1;
            }
        }
        
        CharacterStats {
            total_characters,
            style_counts,
            aliases_count: self.config.aliases.len(),
        }
    }
}

/// 字符统计信息
#[derive(Debug, Clone)]
pub struct CharacterStats {
    /// 总字符数量
    pub total_characters: usize,
    /// 各样式支持的字符数量
    pub style_counts: HashMap<Style, usize>,
    /// 别名数量
    pub aliases_count: usize,
}

impl Default for Unichar {
    fn default() -> Self {
        Self::new()
    }
}

/// 便利函数：创建终端友好的Unichar实例
pub fn terminal() -> Unichar {
    Unichar::with_config(Presets::terminal())
}

/// 便利函数：创建富文本Unichar实例
pub fn rich() -> Unichar {
    Unichar::with_config(Presets::rich())
}

/// 便利函数：创建简洁Unichar实例
pub fn minimal() -> Unichar {
    Unichar::with_config(Presets::minimal())
}

/// 便利函数：创建开发Unichar实例
pub fn development() -> Unichar {
    Unichar::with_config(Presets::development())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_functionality() {
        let unichar = Unichar::new();
        
        // 测试基本字符获取
        assert!(unichar.get("success").is_some());
        assert!(unichar.get("error").is_some());
        assert!(unichar.get("nonexistent").is_none());
    }

    #[test]
    fn test_style_switching() {
        let mut unichar = Unichar::new();
        
        // 测试样式切换
        unichar.set_config(Config::new().with_style(Style::Icon));
        assert!(unichar.get("success").is_some());
        
        unichar.set_config(Config::new().with_style(Style::Simple));
        assert!(unichar.get("success").is_some());
    }

    #[test]
    fn test_aliases() {
        let mut unichar = Unichar::new();
        unichar.set_config(Config::new().add_alias("ok".to_string(), "success".to_string()));
        
        assert_eq!(unichar.get("ok"), unichar.get("success"));
    }

    #[test]
    fn test_formatting() {
        let unichar = Unichar::new();
        let formatted = unichar.format("Status: {success}");
        assert!(formatted.contains("Status:"));
        assert!(formatted.contains(unichar.get("success").unwrap()));
    }

    #[test]
    fn test_custom_characters() {
        let mut unichar = Unichar::new();
        let custom = CharacterSet::new().simple(":)");
        
        unichar.add_character_set("smile".to_string(), custom);
        assert_eq!(unichar.get("smile"), Some(":)"));
    }

    #[test]
    fn test_config_presets() {
        let terminal = terminal();
        let rich = rich();
        let minimal = minimal();
        let development = development();
        
        assert_eq!(terminal.config().style, Style::Simple);
        assert_eq!(rich.config().style, Style::Icon);
        assert_eq!(minimal.config().style, Style::Simple);
        assert_eq!(development.config().style, Style::Icon);
    }

    #[test]
    fn test_fallback() {
        let unichar = Unichar::new();
        let result = unichar.get_with_fallback("success");
        assert!(result.is_some());
    }

    #[test]
    fn test_multiple_get() {
        let unichar = Unichar::new();
        let results = unichar.get_multiple(&["success", "error", "nonexistent"]);
        
        assert!(results.get("success").unwrap().is_some());
        assert!(results.get("error").unwrap().is_some());
        assert!(results.get("nonexistent").unwrap().is_none());
    }

    #[test]
    fn test_stats() {
        let unichar = Unichar::new();
        let stats = unichar.get_stats();
        
        assert!(stats.total_characters > 0);
        assert!(!stats.style_counts.is_empty());
    }
}